using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace A1
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics; // The graphics manager
        SpriteBatch spriteBatch; // The spritebatch
        Texture2D ballSprite; //The ball sprite
        Texture2D horizontalpaddle; // The horizontal paddle sprite
        Texture2D verticalpaddle; // The vertal paddle sprite
        Texture2D powerblock; // The powerblock and powerup sprites
        SpriteFont font; //The game font
        Ball ball; //The ball
        GameState menustate; //The current menu
        GameState gameMode; // The mode of game to play
        Difficulty difficulty; //The difficulty of the game
        private PowerUp powerUp; // The power up object
        MainMenu main; //The main menu
        ControlMenu cMenu; //The control meny
        PowerupBlock pb; //The powerup block
        InputManager inputs; //The inputmanager
        bool firstRun = true; //Whether this is the first run
        bool createdPaddles = false; //Whether we've created any paddles
        int GAME_HEIGHT; //The game height
        int GAME_WIDTH;//The game width
        int players; //the amount of players in game
        int ai; //the amount of ai in game
        GameOverMenu gameEnd; //The game over menu
        int winner; //The winner of the game
        private List<Paddle> paddles; //The list of paddles on screen

        /// <summary>
        /// The difficulty of the game
        /// </summary>
        public enum Difficulty
        {
            Easy,
            Medium,
            Hard
        }

        /// <summary>
        /// The position of the paddles, starting with 1, non-zero based
        /// </summary>
        public enum Position
        {
            Left = 1,
            Right,
            Top,
            Bottom
        }

        /// <summary>
        /// The current state of the game
        /// </summary>
        public enum GameState
        {
            Main,
            FourPlayerElimination,
            FourPlayerCharge,
            TwoPlayer,
            Breakout,
            Setup,
            Help,
            GameOver
        }




        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            graphics.PreferredBackBufferWidth = 700;
            graphics.PreferredBackBufferHeight = 700;
            graphics.ApplyChanges();
            inputs = new InputManager(this);
            Components.Add(inputs);

        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {

            GAME_HEIGHT = graphics.GraphicsDevice.Viewport.Height;
            GAME_WIDTH = graphics.GraphicsDevice.Viewport.Width;
            paddles = new List<Paddle>();
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);



            // TODO: use this.Content to load your game content here

            //Load in the font
            font = Content.Load<SpriteFont>("Fonts/Font");
            powerblock = Content.Load<Texture2D>("Sprites/PowerUps");
            verticalpaddle = Content.Load<Texture2D>("Sprites/Enemy");
            ballSprite = Content.Load<Texture2D>("Sprites/Ball");
            horizontalpaddle = Content.Load<Texture2D>("Sprites/EnemyHorizontal");
            // Load in the Enemy, Player, and Ball sprites

            menustate = GameState.Main;
            difficulty = Difficulty.Medium;
            main = new MainMenu(font, inputs);
            gameMode = GameState.FourPlayerElimination;



        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            //This will run through a main menu, control menu, then the game, and go back to main

            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
            switch (menustate)
            {
                case GameState.Main:
                    menustate = main.Update(ref difficulty, ref gameMode);
                    break;
                case GameState.Setup:
                    if (cMenu == null)
                    {
                        if (!createdPaddles)
                        {
                            //Create the paddles if they haven't been created
                            ball = new Ball(GAME_HEIGHT, GAME_WIDTH, ballSprite, true, false);
                            pb = new PowerupBlock(powerblock, GAME_HEIGHT, GAME_WIDTH, ball);
                            paddles.Add(new AI(horizontalpaddle, Position.Left, ball, GAME_WIDTH, GAME_HEIGHT, difficulty, gameTime));
                            paddles.Add(new AI(horizontalpaddle, Position.Right, ball, GAME_WIDTH, GAME_HEIGHT, difficulty, gameTime));
                            paddles.Add(new AI(horizontalpaddle, Position.Top, ball, GAME_WIDTH, GAME_HEIGHT, difficulty, gameTime));
                            paddles.Add(new AI(horizontalpaddle, Position.Bottom, ball, GAME_WIDTH, GAME_HEIGHT, difficulty, gameTime));
                            createdPaddles = true;
                        }
                        cMenu = new ControlMenu(true, font, gameMode, inputs, paddles, horizontalpaddle, GAME_HEIGHT, GAME_WIDTH, ball, difficulty, gameTime);
                    }
                    else
                    {
                        menustate = cMenu.Update();
                    }
                    break;
                case GameState.FourPlayerElimination:
                    if (firstRun)
                    {

                        for (int i = 0; i < 4; i++)
                        {
                            paddles[i].Score = 10;
                            ball.LeftScore = 10;
                            ball.RightScore = 10;
                            ball.TopScore = 10;
                            ball.BottomScore = 10;
                        }
                        firstRun = false;
                    }
                    else
                    {
                        if (powerUp != null)
                        {
                            powerUp = powerUp.Update(gameTime);
                        }
                        else
                        {
                            powerUp = pb.CollisionDetect();
                            pb.AppearRandomly(gameTime);
                        }

                        ball.Update();

                        //Check if someone had won//

                        players = 0;
                        ai = 0;
                        for (int i = 0; i < paddles.Count; i++)
                        {
                            paddles[i].Update(gameTime);
                            switch (paddles[i].Position)
                            {
                                case Position.Right:
                                    paddles[i].Score = ball.RightScore;
                                    break;
                                case Position.Left:
                                    paddles[i].Score = ball.LeftScore;
                                    break;
                                case Position.Top:
                                    paddles[i].Score = ball.TopScore;
                                    break;
                                case Position.Bottom:
                                    paddles[i].Score = ball.BottomScore;
                                    break;
                            }
                            if (paddles[i] is Player)
                            {
                                players++;
                                winner += i;
                                if (paddles[i].Score <= 0)
                                {
                                    winner -= i;
                                    players--;
                                }
                            }
                            else if (paddles[i] is AI)
                            {
                                ai++;
                                winner += i;
                                if (paddles[i].Score <= 0)
                                {
                                    winner -= i;
                                    ai--;
                                }
                            }
                            if ((ai == 0 && players == 1))
                            {
                                menustate = GameState.GameOver;
                                gameEnd = new GameOverMenu((int)paddles[winner].Position, font);
                            }
                            if ((players == 0 && i == paddles.Count - 1))
                            {
                                menustate = GameState.GameOver;
                                gameEnd = new GameOverMenu(5, font);
                            }


                        }
                    }
                    break;
                case GameState.GameOver:
                    menustate = gameEnd.Update(inputs);
                    firstRun = true;
                    break;
            }




            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            KeyboardState keyState = Keyboard.GetState();
            GraphicsDevice.Clear(Color.Salmon);

            spriteBatch.Begin();


            switch (menustate)
            {
                case GameState.Main:
                    main.Draw(spriteBatch);
                    break;
                case GameState.Setup:
                    if (cMenu != null)
                        cMenu.Draw(spriteBatch);
                    break;
                case GameState.FourPlayerElimination:
                    if (!firstRun)
                    {
                        for (int i = 0; i < paddles.Count; i++)
                        {
                            paddles[i].Draw(spriteBatch);
                        }
                        spriteBatch.Draw(ball.Sprite, ball.Rec, Color.White);
                        pb.Draw(spriteBatch);
                        if (powerUp != null)
                        {
                            powerUp.Draw(spriteBatch);
                        }
                        spriteBatch.DrawString(font, ball.LeftScore + "", new Vector2((GAME_WIDTH / 2) - 50, GAME_HEIGHT / 2), Color.White);
                        spriteBatch.DrawString(font, ball.RightScore + "", new Vector2((GAME_WIDTH / 2) + 50, GAME_HEIGHT / 2), Color.White);
                        spriteBatch.DrawString(font, ball.TopScore + "", new Vector2((GAME_WIDTH / 2), GAME_HEIGHT / 2 - 50), Color.White);
                        spriteBatch.DrawString(font, ball.BottomScore + "", new Vector2((GAME_WIDTH / 2), GAME_HEIGHT / 2 + 50), Color.White);
                    }
                    break;
                case GameState.GameOver:
                    if (gameEnd != null)
                    {
                        gameEnd.Draw(spriteBatch);
                    }
                    break;
            }




            base.Draw(gameTime);

            //always end the spritebatch when you're done drawing
            spriteBatch.End();
        }
    }
}
